package lsy.redis001.lsyredis001.service.impl;

import lsy.redis001.lsyredis001.common.entity.PageResult;
import lsy.redis001.lsyredis001.entity.Article;
import lsy.redis001.lsyredis001.service.ArticleService;
import lsy.redis001.lsyredis001.service.ArticleTagService;
import lsy.redis001.lsyredis001.table.RedisKeyConstant;
import lsy.redis001.lsyredis001.table.RedisTableConstant;
import lsy.redis001.lsyredis001.utils.LsyRedisUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LsyRedisUtils lsyRedisUtils;
    @Autowired
    private ArticleTagService articleTagService;

    private static final int ONE_WEEK_IN_SECONDS = 7 * 86400;
    private static final int VOTE_SCORE = 432;
    private static final int ARTICLES_PER_PAGE = 25;

    public Long addArticle(Article atricle){
        Long incr = lsyRedisUtils.incr(RedisKeyConstant.ARTICLE_KEY, -1);
        // 让id从1开始
        incr ++;
        atricle.setId(incr);

        HashMap<String,Object> map = new HashMap<>();
        map.put("title",atricle.getTitle());
        map.put("author",atricle.getAuthor());
        map.put("img",atricle.getImg());
        map.put("summary",atricle.getSummary());
//        map.put("updateTime",atricle.getUpdateTime());
        redisTemplate.opsForHash().putAll(RedisTableConstant.getArticleId(incr) ,map);

        // 用右边插入，这样lrange是正常的插入顺序。如果用lpush，lrange取的时候是反着的
        redisTemplate.opsForList().rightPush(RedisTableConstant.getPostList(), incr);
        return incr;
    }

    public void editArticleTitle(Long id,String title){
        if(redisTemplate.opsForHash().hasKey(RedisTableConstant.getArticleId(id),"title")){
            redisTemplate.opsForHash().put(RedisTableConstant.getArticleId(id),"title",title);
        }
    }

    public Article getOne(Long id){
        Article article = new Article();
        article.setId(id);
        Map<String,Object> map = redisTemplate.opsForHash().entries(RedisTableConstant.getArticleId(id));
        if(!CollectionUtils.isEmpty(map)){
            try {
                BeanUtils.populate(article,map);

                // 查询文章tags集合
                List<String> tags = articleTagService.getArticleTag(id);
                if(!CollectionUtils.isEmpty(tags)){
                    article.setTags(tags);
                }
                return article;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public PageResult<Article> listPage(Long startPage, Long pageNum){
        // 1、计算分页
        Long totleNum = redisTemplate.opsForList().size(RedisTableConstant.getPostList());
        Long totlePage = totleNum/pageNum + (totleNum % pageNum > 0 ? 1 : 0);

        startPage = (startPage > totlePage) ? totlePage : startPage;

        Long startNum = (startPage - 1) * pageNum + 1;
        Long endNum = startNum + pageNum - 1;
        Long startIndex = startNum-1;
        Long endIndex = endNum-1;
        // 2、获取文章id集合
        List<Integer> range = redisTemplate.opsForList().range(RedisTableConstant.getPostList(), startIndex, endIndex);
        // 3、查询文章
        List<Article> articles = new ArrayList<>();
        for (Integer id : range) {
            Article article = this.getOne(Long.valueOf(id));
            // 查询文章tags集合
            List<String> tags = articleTagService.getArticleTag(Long.valueOf(id));
            if(!CollectionUtils.isEmpty(tags)){
                article.setTags(tags);
            }
            articles.add(article);
        }
        return new PageResult<Article>(totlePage.intValue(),totleNum.intValue(),articles);
    }

    public Boolean deleteArticle(Long id){
        Boolean b = redisTemplate.delete(RedisTableConstant.getArticleId(id));
        // 删除列表里的数据
        redisTemplate.opsForList().remove(RedisTableConstant.getPostList(),1,id);
        return b;
    }
}
